package streamforce.crypto.user;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import streamforce.Stat;
import streamforce.crypto.KPAbe;
import streamforce.crypto.event.TransformedCTEventAll;
import streamforce.crypto.event.TransformedCTEventAllAgg3;
import streamforce.crypto.event.UserInitAggEvent;
import streamforce.crypto.event.UserInitEvent;
import streamforce.crypto.message.PolicyMessage;
import streamforce.crypto.message.UserHandshakeMessage;
import streamforce.crypto.policies.Policy;
import streamforce.crypto.user.subscriber.UserSelectAllSimple;
import streamforce.crypto.user.subscriber.UserSelectPriceSimple;

/**
 * Connecting to the server.
 * 
 * It only has to listen to new messages: initilization and
 * then decryption
 *
 */
public class EPUserClientSimple extends Thread{
	private final Log log = LogFactory.getLog(EPUserClientSimple.class); 
	public final static int SELECT_PRICE=0, SELECT_VOLUME=1, SELECT_ALL=2;
	ObjectInputStream ois=null; 
	ObjectOutputStream oos = null;
	Policy userPolicy; 
	int userId; 
	int type; 
	UserHandshakeMessage uhm; 
	KPAbe cryptoHandler; 
	public EPUserClientSimple(int ui, int type){
		this.userId = ui;
		this.type = type;
		this.initialization();
		int[] ids = {this.userId};
		this.uhm = new UserHandshakeMessage(ids,
				PolicyMessage.SIMPLE_QUERY);
		this.cryptoHandler = new KPAbe();
	}
	
	public void initialization(){
		Properties property = new Properties();
		try {
			property.load(new FileInputStream("attributes.properties"));
			int port = new Integer(property.getProperty("serverPort")).intValue() + 1;
			Socket clientSocket = new Socket(property.getProperty("serverHost"), port);
			this.oos = new ObjectOutputStream(clientSocket.getOutputStream());
			this.ois = new ObjectInputStream(clientSocket.getInputStream());
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//1. sent init message 
	//2. then listen to the TransformedCtEventAll event
	public void run(){
		try {
			this.oos.writeObject(this.uhm);
			log.info("user "+this.userId+": done hanshaking with the server");
			do{
				Object o = this.ois.readObject();
				if (o instanceof UserInitEvent){
					this.initializeUser((UserInitEvent)o); 
				}			
				else if (o instanceof UserInitAggEvent){
					this.initializeUser((UserInitAggEvent) o);
				}
				else if (o instanceof TransformedCTEventAll){						
					this.userPolicy.update((TransformedCTEventAll)o);
				}
				else if (o instanceof TransformedCTEventAllAgg3){
					this.userPolicy.update((TransformedCTEventAllAgg3)o);
				}
				
			}while (true);
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}				
	}
	
	protected void initializeUser(UserInitAggEvent pmu){
		
	}
	
	protected void initializeUser(UserInitEvent pmu){				
		if (this.type==EPUserClientSimple.SELECT_PRICE)
			this.userPolicy = new UserSelectPriceSimple(this.cryptoHandler);
		else if (this.type == EPUserClientSimple.SELECT_ALL)
			this.userPolicy = new UserSelectAllSimple(this.cryptoHandler);
		long start = System.currentTimeMillis(); 
		this.userPolicy.initUser_simple(this.userId, 2, pmu.getPubK()[0],
				pmu.gettK()[0], pmu.getDecK()[0], pmu.getDetK()[0]);
		long end = System.currentTimeMillis(); 
		log.info("user "+this.userId+" initialization time = "+(end-start)); 
	}
		
	public static void main(String[] args){
		int id = new Integer(args[0]).intValue();
		Timer t = new Timer("User task", true);    	
    	t.scheduleAtFixedRate(new TimerTask(){
    		public void run(){
    			Stat.aggregateAndResetAll("userThroughput");     			
    		}
    	}, 0, 1000);
    	
		(new EPUserClientSimple(id,EPUserClientSimple.SELECT_ALL)).start();
	}
}
